﻿using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using FytSoa.Common.Utils;
using FytSoa.Domain.Core.Result;
using FytSoa.Domain.User;
using FytSoa.DynamicApi.Attributes;
using FytSoa.Sugar;
using Masuit.Tools;
using Masuit.Tools.Security;
using Microsoft.AspNetCore.Mvc;

namespace FytSoa.Application.App;

[Route("app/login")]
[ApiExplorerSettings(GroupName = "v5")]
public class LoginService : IApplicationService
{
    private readonly SugarRepository<Member> _thisRepository;
    public LoginService(SugarRepository<Member> thisRepository)
    {
        _thisRepository = thisRepository;
    }
    
    /// <summary>
    /// 登录
    /// </summary>
    /// <param name="code"></param>
    [HttpGet("code/{code}")]
    public string LoginAsync(string code)
    {
        var appId = AppUtils.Configuration["oauth:wechat:app_id"];
        var appKey = AppUtils.Configuration["oauth:wechat:app_key"];
        var url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appKey + "&js_code=" +
                  code + "&grant_type=authorization_code";
        var codeRes = HttpUtils.HttpGet(url);
        Logger.Info("codeRes：" + codeRes);
        if (codeRes.Contains("errcode")) return "获得code失败~";
        //授权成功
        var key = JsonSerializer.Deserialize<LoginCodeDto>(codeRes);
        return key.openid;
    }

    /// <summary>
    /// 注册
    /// </summary>
    /// <returns></returns>
    [HttpPost("register")]
    public async Task<LoginSuccessDto> RegisterAsync(AppRegisterParam param)
    {
        Logger.Info("注册参数1：" + JsonSerializer.Serialize(param));
        try
        {
            var appId = AppUtils.Configuration["oauth:wechat:app_id"];
            var appKey = AppUtils.Configuration["oauth:wechat:app_key"];
            var url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appKey +
                      "&js_code=" + param.WxCode + "&grant_type=authorization_code";
            var codeRes = await HttpUtils.HttpGetAsync(url);
            if (codeRes.Contains("errcode")) throw new ArgumentException("获得code失败~");
            //授权成功
            var key = JsonSerializer.Deserialize<LoginCodeDto>(codeRes);
            //Logger.Info("注册参数2：" + key);
            
            //读取手机号码
            param.Mobile = GetPhoneNumber(param.EncryptedData, param.Iv, key.session_key);
            
            var modelByCode = await _thisRepository.GetSingleAsync(m => m.OpenId == key.openid);
            //Logger.Info("注册参数3：" + JsonSerializer.Serialize(modelByCode));
            if (modelByCode != null && !string.IsNullOrEmpty(modelByCode.OpenId))
            {
                return new LoginSuccessDto()
                {
                    Id = modelByCode.Id,
                    NickName = modelByCode.NickName,
                    AvatarUrl = modelByCode.HeadPic,
                    Point = modelByCode.Point,
                    Mobile = modelByCode.Mobile.Mask()
                };
            }

            var isMobile = await _thisRepository.GetSingleAsync(m => m.Mobile == param.Mobile);
            if (isMobile != null && !string.IsNullOrEmpty(isMobile.Mobile))
            {
                throw new ArgumentException("手机号码已注册，请更换~");
            }

            var member = new Member()
            {
                Id = Unique.Id(),
                GroupId = 1471788590005620738,
                LoginName = "111111",
                LoginPwd = "A123456!".MDString(),
                NickName = param.NickName,
                WxName = param.WxName.FilterEmoji(),
                HeadPic = param.AvatarUrl,
                Mobile = param.Mobile,
                Sex = "男",
                Status = true,
                OpenId = key?.openid
            };
            await _thisRepository.InsertAsync(member);
            return new LoginSuccessDto()
            {
                Id = member.Id,
                NickName = param.NickName,
                AvatarUrl = param.AvatarUrl,
                Point = member.Point,
                WxName = param.WxName.FilterEmoji(),
                Mobile = member.Mobile.Mask()
            };
        }
        catch (Exception ex)
        {
            Logger.Error("登录失败，具体信息：" + ex.Message);
            throw new ArgumentException(ex.Message);
        }
    }

    /// <summary>
    /// 修改姓名
    /// </summary>
    /// <param name="param"></param>
    [HttpPost("modify/name")]
    public async Task<ApiResult<bool>> ModifyNickName(AppModifyName param)
    {
        return JResult<bool>.Success(await _thisRepository.UpdateAsync(m => new Member()
        {
            NickName = param.NickName
        }, m => m.Id == param.Id));
    }

    [NonDynamicMethod]
    private string GetPhoneNumber(string encryptedData, string iv, string sessionKey)
    {
        try
        {
            byte[] encryData = Convert.FromBase64String(encryptedData);
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Key = Convert.FromBase64String(sessionKey);
            rijndaelCipher.IV = Convert.FromBase64String(iv);
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;
            ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
            byte[] plainText = transform.TransformFinalBlock(encryData, 0, encryData.Length);
            string result = Encoding.Default.GetString(plainText);

            dynamic model = Newtonsoft.Json.Linq.JToken.Parse(result) as dynamic;
            string phoneNumber = model.phoneNumber;
            return string.IsNullOrEmpty(phoneNumber) ? "" : phoneNumber;
        }
        catch (Exception ex)
        {
            Logger.Error("获得微信小程序手机号码：" + ex.Message);
            return "";
        }
    }
}